package com.shuziren.question.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.shuziren.abnormal.CustomException;
import com.shuziren.question.entity.dto.InsertInterviewQuestionDTO;
import com.shuziren.question.entity.dto.InterviewQuestionDTO;
import com.shuziren.question.entity.*;
import com.shuziren.question.entity.dto.SelectInterviewQuestionDTO;
import com.shuziren.question.entity.dto.UpdateInterviewQuestionDTO;
import com.shuziren.question.entity.vo.QuestionCategoryVO;
import com.shuziren.question.entity.vo.SelectByQuestion;
import com.shuziren.question.mapper.*;
import com.shuziren.question.service.InterviewQuestionService;
import com.shuziren.question.service.InterviewQuestionSetService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.yaml.snakeyaml.events.Event;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

@Service
@SuppressWarnings("all")
public class InterviewQuestionServiceImpl extends ServiceImpl<InterviewQuestionMapper, InterviewQuestion> implements InterviewQuestionService {


    @Autowired
    private InterviewQuestionMapper interviewQuestionMapper;

    @Autowired
    private SortandtopicMapper sortandtopicMapper;

    @Autowired
    private ProblemsetandtopicMapper problemsetandtopicMapper;

    @Autowired
    private QuestionCategoryMapper questionCategoryMapper;

    @Autowired
    private InterviewQuestionSetMapper interviewQuestionSetMapper;

    @Autowired
    private InterviewQuestionSetService interviewQuestionSetService;


    /**
     * 添加问题
     * @param question
     * @return 返回 添加结果
     */
    @Override
    @Transactional(isolation = Isolation.READ_UNCOMMITTED, propagation = Propagation.NESTED) // 明确指定所有异常都触发回滚
    public String addQuestion(InsertInterviewQuestionDTO question) throws CustomException {

        InterviewQuestion interviewQuestion = new InterviewQuestion();
        BeanUtils.copyProperties(question,interviewQuestion);
        int insert3 = interviewQuestionMapper.insert(interviewQuestion);
        if (insert3 <= 0){
            throw new CustomException("题目添加失败");
        }
        //如果存在题目集集合，则插入
        if (!question.getQuestionSetIds().isEmpty()){
            List<Integer> questionSetIds = question.getQuestionSetIds();

            for (Integer questionSetId : questionSetIds) {
                InterviewQuestionSet interviewQuestionSet = interviewQuestionSetMapper.selectById(questionSetId);
                if (interviewQuestionSet == null){throw new CustomException("数据异常请稍后再试");}
                int insert = problemsetandtopicMapper.insert(new ProblemsetTopic(questionSetId, interviewQuestion.getId()));
                if (insert <= 0){throw new CustomException("数据异常");}
                int i = interviewQuestionSetService.dataUpdateQuestionSet(questionSetId);
                if (i <= 0){throw new CustomException("数据异常");}
            }

        }
        // 如果存在分类集合，则插入
        if (!question.getCategoryIds().isEmpty()){
            List<Integer> categoryIds = question.getCategoryIds();
            for (Integer categoryId : categoryIds) {
                QuestionCategory questionCategory = questionCategoryMapper.selectById(categoryId);
                if (questionCategory == null){throw new CustomException("数据异常请稍后再试");}
                int insert = sortandtopicMapper.insert(new SortTopic(categoryId, interviewQuestion.getId()));
                if (insert <= 0){throw new CustomException("数据异常");}
            }
        }


        // 返回成功信息
        return "添加成功";
    }




    /**
     * 根据 ID 查询问题
     * @param id
     * @return 返回详情
     */
    @Override
    public SelectByQuestion selectQuestionAndCategoryById(Integer id) {
        if (id == null){
            return null;
        }
        SelectByQuestion selectByQuestion = new SelectByQuestion();
        InterviewQuestion interviewQuestion = interviewQuestionMapper.selectById(id);
        if (interviewQuestion == null){
            return null;
        }
        BeanUtils.copyProperties(interviewQuestion,selectByQuestion);
        List<ProblemsetTopic> problemsetTopics = problemsetandtopicMapper.selectList(new QueryWrapper<ProblemsetTopic>().eq("topic_id", id));
        if (!problemsetTopics.isEmpty()){
            ArrayList<Integer> list = new ArrayList<>();
            for (ProblemsetTopic problemsetTopic : problemsetTopics){
                list.add(problemsetTopic.getQuestionsetId());
            }
            selectByQuestion.setQuestionSets(list);
        }

        List<SortTopic> topicId = sortandtopicMapper.selectList(new QueryWrapper<SortTopic>().eq("topic_id", id));
        if (!topicId.isEmpty()){
            ArrayList<Integer> list = new ArrayList<>();
            for (SortTopic sortTopic : topicId) {
                list.add(sortTopic.getSortId());
            }
            selectByQuestion.setCategories(list);
        }
        return selectByQuestion;
    }


    /**
     * 根据条件查询问题，并分页返回结果。
     * @param interviewQuestion 包含查询条件的 InterviewQuestion 对象
     * @return 返回分页后的 InterviewQuestion 列表
     */
    @Override
    public IPage<InterviewQuestion> getAllQuestions(SelectInterviewQuestionDTO interviewQuestion) {
        MPJLambdaWrapper<InterviewQuestion> MPJLambdaWrapper = new MPJLambdaWrapper<>();
        MPJLambdaWrapper.select(InterviewQuestion::getId,
                InterviewQuestion::getTitle,
                InterviewQuestion::getDifficulty,
                InterviewQuestion::getCreatedAt,
                InterviewQuestion::getStatus,
                InterviewQuestion::getScore)
                .selectCollection(QuestionCategory.class,InterviewQuestion::getCategories,
                        map->map.id(QuestionCategory::getId
                                , QuestionCategoryVO::getId)
                                .result(QuestionCategory::getName, QuestionCategoryVO::getName));
        if (interviewQuestion.getTitle() != null && !interviewQuestion.getTitle().isEmpty()){
            MPJLambdaWrapper.like(InterviewQuestion::getTitle, interviewQuestion.getTitle());
        }
        if (interviewQuestion.getDifficulty() != null && interviewQuestion.getDifficulty() != 0){
            MPJLambdaWrapper.eq(InterviewQuestion::getDifficulty, interviewQuestion.getDifficulty());
        }
        if (interviewQuestion.getStatus() != null && interviewQuestion.getStatus() != 0){
            MPJLambdaWrapper.eq(InterviewQuestion::getStatus, interviewQuestion.getStatus());
        }

        MPJLambdaWrapper.leftJoin(SortTopic.class, SortTopic::getTopicId, InterviewQuestion::getId).leftJoin(QuestionCategory.class, QuestionCategory::getId, SortTopic::getSortId);
        IPage<InterviewQuestion> interviewQuestionIPage = new Page<>(interviewQuestion.getPageNum(), interviewQuestion.getPageSize());
        IPage<InterviewQuestion> interviewQuestionIPage1 = interviewQuestionMapper.selectJoinPage(interviewQuestionIPage, InterviewQuestion.class, MPJLambdaWrapper);

        return interviewQuestionIPage1;
    }




    /**
     * 删除问题
     * @param id
     * @return 返回删除结果
     */
    @Override
    public String deleteQuestions(int id) throws CustomException{
        if (id == 0) {
            throw new CustomException("题目不存在");
        }
        InterviewQuestion interviewQuestion = interviewQuestionMapper.selectById(id);
        if (interviewQuestion == null) {
            throw new CustomException("题目不存在");
        }

        // 删除题目
        QueryWrapper<InterviewQuestion> wrapper1 = new QueryWrapper<InterviewQuestion>().eq("id", id);
        int delete1 = interviewQuestionMapper.delete(wrapper1);
        if (delete1 <= 0) {
            throw new CustomException("删除失败");
        }


        // 删除题目与题目集的关联记录
        QueryWrapper<ProblemsetTopic> wrapper = new QueryWrapper<ProblemsetTopic>().eq("topic_id", id);
        List<ProblemsetTopic> problemsetTopics = problemsetandtopicMapper.selectList(wrapper);
        int delete = problemsetandtopicMapper.delete(wrapper);
        if (delete <= 0) {
            throw new CustomException("删除失败");
        }

        for (ProblemsetTopic problemsetTopic : problemsetTopics) {
            int i = interviewQuestionSetService.dataUpdateQuestionSet(problemsetTopic.getQuestionsetId());
            if (i <= 0){
                throw new CustomException("题目不存在");
            }
        }


        return "删除成功";
    }

    /**
     * 修改题目
     * @param updateInterviewQuestionDTO 更新面试问题的DTO
     * @return 更新是否成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateQuestion(UpdateInterviewQuestionDTO updateInterviewQuestionDTO) {
        // 参数校验
        if (!isValidUpdateDTO(updateInterviewQuestionDTO)) {
            throw new IllegalArgumentException("无效的更新参数");
        }

        try {
            // 更新基本信息
            if (!updateBasicInfo(updateInterviewQuestionDTO)) {
                throw new CustomException("更新基本信息失败");
            }

            // 更新类别关联
            updateCategories(updateInterviewQuestionDTO);

            // 更新问题集关联
            updateQuestionSets(updateInterviewQuestionDTO);

            return true;
        } catch (Exception e) {
            throw new CustomException("更新面试问题失败: " + e.getMessage());
        }
    }

    /**
     * 验证更新DTO的有效性
     */
    private boolean isValidUpdateDTO(UpdateInterviewQuestionDTO dto) {
        return dto != null && dto.getId() != null;
    }

    /**
     * 更新面试问题基本信息
     */
    private boolean updateBasicInfo(UpdateInterviewQuestionDTO dto) {
        InterviewQuestion interviewQuestion = new InterviewQuestion();
        // 修正BeanUtils.copyProperties的参数顺序
        org.springframework.beans.BeanUtils.copyProperties(dto, interviewQuestion);

        return interviewQuestionMapper.updateById(interviewQuestion) > 0;
    }

    /**
     * 更新类别关联
     */
    private void updateCategories(UpdateInterviewQuestionDTO dto) {
        if (dto.getCategories() == null || dto.getCategories().isEmpty()) {
            return;
        }

        // 获取现有类别
        List<Long> existingCategoryIds = sortandtopicMapper.selectObjs(
                        new QueryWrapper<SortTopic>()
                                .eq("topic_id", dto.getId())
                                .select("sort_id")
                ).stream()
                .map(obj -> ((Number) obj).longValue())
                .toList();

        // 新类别列表
        List<Long> newCategories = dto.getCategories().stream()
                .map(Long::valueOf)
                .toList();

        // 计算需要删除和添加的类别
        List<Long> toDelete = existingCategoryIds.stream()
                .filter(id -> !newCategories.contains(id))
                .toList();
        List<Long> toAdd = newCategories.stream()
                .filter(id -> !existingCategoryIds.contains(id))
                .toList();

        // 批量删除不再关联的类别
        if (!toDelete.isEmpty()) {
            sortandtopicMapper.delete(
                    new QueryWrapper<SortTopic>()
                            .eq("topic_id", dto.getId())
                            .in("sort_id", toDelete)
            );
        }

        // 批量插入新类别关联
        if (!toAdd.isEmpty()) {
            List<SortTopic> insertList = toAdd.stream()
                    .map(id -> new SortTopic(Math.toIntExact(id), dto.getId()))
                    .toList();

            for (SortTopic sortTopic : insertList) {
                //根据ID获取是有存在题目分类
                if (questionCategoryMapper.selectById(sortTopic.getSortId()) == null) {
                    throw new CustomException("修改异常请重试");
                }
                if (sortandtopicMapper.insert(sortTopic) != 1) {
                    throw new CustomException("添加类别关联失败");
                }
            }
        }
    }

    /**
     * 更新问题集关联
     */
    private void updateQuestionSets(UpdateInterviewQuestionDTO dto) {
        if (dto.getQuestionSets() == null || dto.getQuestionSets().isEmpty()) {
            return;
        }

        // 获取现有问题集
        List<Long> existingQuestionSets = problemsetandtopicMapper.selectObjs(
                        new QueryWrapper<ProblemsetTopic>()
                                .eq("topic_id", dto.getId())
                ).stream()
                .map(obj -> ((Number) obj).longValue())
                .toList();

        // 新问题集列表
        List<Long> newQuestionSets = dto.getQuestionSets().stream()
                .map(Long::valueOf)
                .toList();

        // 计算需要删除和添加的问题集
        List<Long> toDelete = existingQuestionSets.stream()
                .filter(id -> !newQuestionSets.contains(id))
                .toList();
        List<Long> toAdd = newQuestionSets.stream()
                .filter(id -> !existingQuestionSets.contains(id))
                .toList();

        // 批量删除不再关联的问题集
        if (!toDelete.isEmpty()) {
            int deleteCount = problemsetandtopicMapper.delete(
                    new QueryWrapper<ProblemsetTopic>()
                            .eq("topic_id", dto.getId())
                            .in("problemset_id", toDelete)
            );
            if (deleteCount != toDelete.size()) {
                throw new CustomException("删除问题集关联失败");
            }
            toDelete.forEach(id -> {
                int i = interviewQuestionSetService.dataUpdateQuestionSet(id.intValue());
                if (i <= 0)  {throw new CustomException("修改异常请重试");}
            });
        }

        // 批量插入新问题集关联
        if (!toAdd.isEmpty()) {
            List<ProblemsetTopic> insertList = toAdd.stream()
                    .map(id -> new ProblemsetTopic(id.intValue(), dto.getId()))
                    .toList();

            for (ProblemsetTopic problemsetTopic : insertList) {
                if (interviewQuestionSetMapper.selectById(problemsetTopic.getQuestionsetId()) == null) {
                    throw new CustomException("修改异常请重试");
                }
                if (problemsetandtopicMapper.insert(problemsetTopic) != 1) {
                    throw new CustomException("添加问题集关联失败");
                }
                int i = interviewQuestionSetService.dataUpdateQuestionSet(problemsetTopic.getQuestionsetId());
                if (i <= 0)  {throw new CustomException("修改异常请重试");}
            }
        }
    }

}